#!/usr/bin/env python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

# Copyright (c) 2019-2020 Fpemud <fpemud@sina.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

"""
manpa

@author: Fpemud
@license: GPLv3 License
@contact: fpemud@sina.com
"""

import os
import shutil
import tempfile
from .manpa_util import ManpaUtil
from .manpa_client_selenium import ManpaSeleniumWebDriver
from .manpa_client_playwright import ManpaPlaywrightClient
from .manpa_downloader import ManpaDownloader


__author__ = "fpemud@sina.com (Fpemud)"
__version__ = "0.0.1"


"""
function list:
1. headless by xvfb, gtk-broadway, view UI any time
2. fake-useragent
3. select proxy from pool
4. control downloader
6. auto add delay
7. detect and solve interception
8. save video as log
"""


class Manpa:

    DEFAULT_WIDTH = 1280
    DEFAULT_HEIGHT = 720

    def __init__(self, width=None, height=None, tmp_dir=None, proxies=None, videoLogFile=None, isDebug=False):
        self._width = width if width is not None else self.DEFAULT_WIDTH
        self._height = height if height is not None else self.DEFAULT_HEIGHT
        self._colordepth = 24

        if proxies is not None:
            self._proxyList = proxies
        else:
            self._proxyList = []

        if tmp_dir is not None:
            self._tmpDir = tmp_dir
            self._bAutoRemoveTmpDir = False
        else:
            self._tmpDir = tempfile.mkdtemp()
            self._bAutoRemoveTmpDir = True
        ManpaUtil.removeDirContentExclude(self._tmpDir, [])

        self._tmpUserDataDir = os.path.join(self._tmpDir, "user-data")
        os.mkdir(self._tmpUserDataDir)
        self._tmpDownloadDir = os.path.join(self._tmpDir, "downloads")
        os.mkdir(self._tmpDownloadDir)

        self._videoLogFile = videoLogFile
        self._isDebug = isDebug

        self._httpClientList = []           # can be modified by client object
        self._seleniumClientList = []       # can be modified by client object
        self._playwrightClientList = []     # can be modified by client object
        self._downloaderList = []           # can be modified by client object
        self._intercepted = False           # can be modified by client object

        self._warnCallback = self._defaultWarnCallback

    def dispose(self):
        self._warnCallback = None
        self._intercepted = None
        self._downloaderList = None
        self._seleniumClientList = None
        self._playwrightClientList = None
        self._httpClientList = None

        self._isDebug = None
        self._videoLogFile = None

        self._tmpDownloadDir = None
        self._tmpUserDataDir = None

        if self._bAutoRemoveTmpDir:
            shutil.rmtree(self._tmpDir)
        self._bAutoRemoveTmpDir = None
        self._tmpDir = None

        self._colordepth = None
        self._height = None
        self._width = None

    def __enter__(self):
        return self

    def __exit__(self, type, value, traceback):
        self.dispose()

    def set_warning_callback(self, warning_callback):
        if warning_callback is not None:
            self._warnCallback = warning_callback
        else:
            self._warnCallback = self._defaultWarnCallback

    def has_been_intercepted(self):
        return self._intercepted

    def open_webclient(self, webclient_name):
        if webclient_name == "simple":
            return None
        elif webclient_name == "selenium":
            return ManpaSeleniumWebDriver(self)
        elif webclient_name == "playwright":
            return ManpaPlaywrightClient(self)
        else:
            assert False

    def open_downloader(self):
        return ManpaDownloader(self)

    # deprecated
    def open_http_client(self):
        return self.open_webclient("simple")

    # deprecated
    def open_selenium_client(self):
        return self.open_webclient("selenium")

    def _defaultWarnCallback(self, msg):
        pass
